package io.renren.modules.member.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import io.renren.common.utils.*;
import io.renren.modules.member.dao.MemberDao;
import io.renren.modules.member.entity.MemberEntity;
import io.renren.modules.member.enums.MemberTypeEnums;
import io.renren.modules.member.enums.SexEnums;
import io.renren.modules.member.service.MemberService;
import org.apache.commons.lang.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.BeanUtils;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;

import java.math.BigDecimal;
import java.util.*;
import java.util.stream.Collectors;

@Service("memberService")
public class MemberServiceImpl extends ServiceImpl<MemberDao, MemberEntity> implements MemberService {

    private final Logger logger = LoggerFactory.getLogger(MemberServiceImpl.class);

    @Override
    public PageUtils queryPage(Map<String, Object> params) {
        String studentCode = (String) params.get("studentCode");
        String type = (String) params.get("type");
        String name = (String) params.get("name");
        String sex = (String) params.get("sex");

        IPage<MemberEntity> page = this.page(
                new Query<MemberEntity>().getPage(params),
                new QueryWrapper<MemberEntity>()
                        .like(StringUtils.isNotBlank(name), "name", name)
                        .like(StringUtils.isNotBlank(studentCode),"student_code", studentCode)
                        .eq(StringUtils.isNotBlank(type),"type", type)
                        .eq(StringUtils.isNotBlank(sex),"sex", sex)

        );
        return new PageUtils(page);
    }

    public MemberEntity findByStudentCode(String studentCode) {
        return baseMapper.findByStudentCode(studentCode);
    }

    public List<MemberEntity> findByCondition(Map<String, Object> params) {
        String studentCode = (String) params.get("studentCode");
        String type = (String) params.get("type");
        String name = (String) params.get("name");
        String sex = (String) params.get("sex");
        String icCode = (String) params.get("icCode");
        return this.list(new QueryWrapper<MemberEntity>()
                        .like(StringUtils.isNotBlank(name), "name", name)
                        .like(StringUtils.isNotBlank(studentCode),"student_code", studentCode)
                        .eq(StringUtils.isNotBlank(sex),"sex", sex)
                        .eq(StringUtils.isNotBlank(icCode),"ic_code", icCode)
                        .eq(StringUtils.isNotBlank(type),"type", type) );
    }

    public List<List<String>> downExcelByCondition(Map<String, Object> params, List<String> titles) {
        String[] titleArr = {"编号", "姓名", "性别", "出生日期", "人员类别", "IC编码"};
        titles.addAll(Arrays.asList(titleArr));
        List<MemberEntity> entities = findByCondition(params);
        if (CollectionUtils.isEmpty(entities)) {
            return new ArrayList<>();
        }
        return entities.stream().map(e -> {
            List<String> rowValues = new ArrayList<>();
            rowValues.add(e.getStudentCode());
            rowValues.add(e.getName());
            rowValues.add(SexEnums.getTextFromCode(e.getSex()));
            rowValues.add(Objects.nonNull(e.getBirthday()) ? DateUtils.format(e.getBirthday()) : "");
            rowValues.add(MemberTypeEnums.getTextFromCode(e.getType()));
            rowValues.add(e.getIcCode());
            return rowValues;
        }).collect(Collectors.toList());
    }

    public Integer batchSaveExcelMember(List<List<Object>> list, Map<String, Integer> position) {
        List<MemberEntity> entities = list.stream().map(e -> {
            MemberEntity excelEntity = new MemberEntity();
            excelEntity.setStudentCode(getValue(e, position, "studentCode", String.class));
            excelEntity.setName(getValue(e, position, "name", String.class));
            excelEntity.setSex(SexEnums.getCodeFromText(getValue(e, position, "sex", String.class)));
            excelEntity.setBirthday(getValue(e, position, "birthday", Date.class));
            excelEntity.setType(MemberTypeEnums.getCodeFromText(getValue(e, position, "type", String.class)));
            excelEntity.setIcCode(getValue(e, position, "icCode", String.class));
            return excelEntity;
        }).collect(Collectors.toList());
        int count = 0;
        for (MemberEntity entity : entities) {
            try {
                Boolean result = saveOrUpdateExcelMember(entity);
                if (result) {
                    count ++;
                }
            } catch (Exception e) {
                logger.error("Excel导入保存数据失败：{}", entity.toString());
                logger.error("Excel导入保存数据失败信息：{}", e);
            }
        }
        return count;
    }

    private Boolean saveOrUpdateExcelMember(MemberEntity excelEntity) {
        if (StringUtils.isBlank(excelEntity.getStudentCode())) {
            return Boolean.FALSE;
        }
        MemberEntity entity = baseMapper.findByStudentCode(excelEntity.getStudentCode());
        if (Objects.nonNull(entity)) {
            excelEntity.setId(entity.getId());
            BeanUtils.copyProperties(excelEntity, entity);
            entity.setUpdateDate(new Date());
            baseMapper.updateById(entity);
        } else {
            entity = excelEntity;
            entity.setCreateDate(new Date());
            baseMapper.insert(entity);
        }
        return Boolean.TRUE;
    }

    /**
     * 根据生日计算年龄
     * @param entity
     */
//    public void calcAge(MemberEntity entity) {
//        if (Objects.nonNull(entity) && Objects.nonNull(entity.getBirthday())) {
//            LocalDate begin = LocalDateUtils.getLocalDateFromDate(entity.getBirthday());
//            LocalDate end = LocalDateUtils.getLocalDateFromDate(new Date());
//            int age = begin.until(end).getYears();
//            entity.setAge(age);
//        }
//    }

    /**
     * 检查ICCODE是否唯一
     * @param entity
     * @return
     */
    public String checkIcCode(MemberEntity entity) {
        if (StringUtils.isBlank(entity.getIcCode())) {
            return null;
        }
        List<MemberEntity> oldEntitys = baseMapper.findByIcCode(entity.getIcCode());
        if (CollectionUtils.isEmpty(oldEntitys)) {
            return null;
        }
        if (Objects.isNull(entity.getId())) {
            return oldEntitys.get(0).getStudentCode();
        }
        for (MemberEntity temp : oldEntitys) {
            if (temp.getId() != entity.getId()) {
                return temp.getStudentCode();
            }
        }
        return null;
    }

    /**
     * obj to string
     * @param obj
     * @return
     */
    private String getStr(Object obj) {
        if (Objects.isNull(obj)) {
            return null;
        }
        String result = String.valueOf(obj);
        if (StringUtils.equals(result, "NULL") || StringUtils.equals(result, "null")) {
            return null;
        } else {
            return result;
        }
    }

    /**
     * 从list中获取对应属性值
     * @param list 属性值
     * @param position 属性对应list中的位置映射
     * @param fieldName 属性名称
     * @param clazz 返回数据类型
     * @return
     */
    private <T> T getValue(List<Object> list, Map<String, Integer> position, String fieldName, Class clazz) {
        Integer index = position.get(fieldName);
        if (Objects.isNull(index)) {
            return null;
        }
        if (index >= list.size()) {
            return null;
        }
        String result = String.valueOf(list.get(index));
        if (StringUtils.equals(result, "NULL") || StringUtils.equals(result, "null")) {
            result = null;
        }
        if (StringUtils.isBlank(result)) {
            return null;
        }
        result = result.trim();
        if (clazz == String.class) {
            return (T) result;
        }
        if (clazz == Integer.class) {
            return (T) new Integer((String) result);
        }
        if (clazz == Long.class) {
            return (T) new Long((String) result);
        }
        if (clazz == BigDecimal.class) {
            return (T) new BigDecimal((String) result);
        }
        if (clazz == Date.class) {
            return (T) DateUtils.dateFrom(result);
        }
        logger.info("数据元素类型无法解析：{}", result);
        return null;
    }
}
